#include "todayleftsecondstest.h"
#include <stdexcept>

void TodayLeftSecondsTest::initTestCase()
{
    qDebug() << "=== 初始化 TodayLeftSeconds 测试用例 ===";

    // 初始化路径
    testDataFileBase = getTestDataBasePath();
    testResultFileBase = getTestResultBasePath();

    qDebug() << "测试数据基础路径:" << testDataFileBase;
    qDebug() << "测试结果基础路径:" << testResultFileBase;

    // 验证路径
    QDir testDataDir(testDataFileBase);
    if (!testDataDir.exists()) {
        qFatal("❌ 测试数据目录不存在: %s", testDataFileBase.toUtf8().constData());
    }

    QDir testResultDir(testResultFileBase);
    if (!testResultDir.exists()) {
        qDebug() << "创建测试结果目录...";
        if (testResultDir.mkpath(".")) {
            qDebug() << "✅ 测试结果目录创建成功";
        } else {
            qWarning() << "❌ 测试结果目录创建失败";
        }
    }

    qDebug() << "✅ TodayLeftSeconds 测试环境初始化完成";
}

QString TodayLeftSecondsTest::getTestDataBasePath()
{
    QDir currentDir(QDir::currentPath());

    // 从构建目录回退5级到 algorithm-test 目录
    QDir targetDir = currentDir.filePath("../../../../../test_data");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试数据:" << absolutePath;
        return absolutePath;
    } else {
        qWarning() << "❌ 相对路径找不到测试数据，使用硬编码路径";
        return "D:/Work/algorithm-test/test_data/";
    }
}

QString TodayLeftSecondsTest::getTestResultBasePath()
{
    QDir currentDir(QDir::currentPath());

    // 从构建目录回退5级到 algorithm-test 目录
    QDir targetDir = currentDir.filePath("../../../../../test_result");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试结果路径:" << absolutePath;
        return absolutePath;
    } else {
        // 尝试创建目录
        if (targetDir.mkpath(".")) {
            qDebug() << "✅ 创建测试结果路径:" << absolutePath;
            return absolutePath;
        } else {
            qWarning() << "❌ 无法创建测试结果路径，使用硬编码路径";
            return "D:/Work/algorithm-test/test_result/";
        }
    }
}

QJsonObject TodayLeftSecondsTest::readJsonObject(const QString& filePath)
{
    qDebug() << "读取JSON对象文件:" << filePath;

    QFileInfo fileInfo(filePath);
    qDebug() << "文件绝对路径:" << fileInfo.absoluteFilePath();
    qDebug() << "文件是否存在:" << fileInfo.exists();

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString errorMsg = QString("无法打开文件：%1").arg(filePath);
        qWarning() << errorMsg;
        throw std::runtime_error(errorMsg.toStdString());
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull()) {
        qWarning() << "JSON解析失败，文件内容:" << QString(data).left(100) << "...";
        throw std::runtime_error("JSON解析失败");
    }

    qDebug() << "JSON对象解析成功，键数量:" << doc.object().keys().size();
    return doc.object();
}

void TodayLeftSecondsTest::createFileRecursion(const QString& fileName)
{
    qDebug() << "创建文件:" << fileName;

    QFileInfo fileInfo(fileName);
    QDir dir = fileInfo.absoluteDir();

    if (!dir.exists()) {
        qDebug() << "创建目录...";
        if (dir.mkpath(".")) {
            qDebug() << "目录创建成功";
        } else {
            qWarning() << "目录创建失败";
        }
    }

    QFile file(fileName);
    if (!file.exists()) {
        if (file.open(QIODevice::WriteOnly)) {
            qDebug() << "文件创建成功";
            file.close();
        } else {
            qWarning() << "文件创建失败";
        }
    } else {
        qDebug() << "文件已存在";
    }
}

QTime TodayLeftSecondsTest::parseTime(const QString& timeStr)
{
    if (timeStr.isEmpty()) {
        return QTime();
    }

    // 处理类似 "09:00:00" 的时间字符串
    QTime time = QTime::fromString(timeStr, "hh:mm:ss");
    if (!time.isValid()) {
        qWarning() << "时间格式无效:" << timeStr;
        throw std::runtime_error("Invalid time format: " + timeStr.toStdString());
    }

    return time;
}

void TodayLeftSecondsTest::writeResultToFile(const QString& fileName, int result)
{
    createFileRecursion(fileName);
    QFile resultFile(fileName);
    if (resultFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QTextStream resultStream(&resultFile);
        resultStream << result;
        resultFile.close();
        qDebug() << "结果写入文件:" << fileName << "值:" << result;
    } else {
        qWarning() << "无法创建结果文件：" << fileName;
    }
}

void TodayLeftSecondsTest::testTodayLeftSeconds()
{
    qDebug() << "=== 开始测试 TodayLeftSeconds 方法 ===";
    qDebug() << "测试数据基础路径:" << testDataFileBase;
    qDebug() << "测试结果基础路径:" << testResultFileBase;

    // 遍历 random_case_1 到 random_case_50 文件夹以及 manual_case_1 到 manual_case_2 文件夹
    for (int i = 1; i <= 52; i++) {
        try {
            QString folderPath;
            QString resultFileName;

            if (i <= 50) {
                folderPath = testDataFileBase + QString("todayLeftSeconds/random_case_%1/").arg(i);
                resultFileName = testResultFileBase + QString("todayLeftSeconds_c/random_case_%1.txt").arg(i);
            } else {
                folderPath = testDataFileBase + QString("todayLeftSeconds/manual_case_%1/").arg(i - 50);
                resultFileName = testResultFileBase + QString("todayLeftSeconds_c/manual_case_%1.txt").arg(i - 50);
            }

            QDir folder(folderPath);
            if (!folder.exists()) {
                qWarning() << "文件夹不存在：" << folderPath;
                continue;
            }

            qDebug() << "\n=== 处理测试用例" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "===";

            // 加载测试数据
            QString testCasesPath = folderPath + "test_cases.json";
            QJsonObject testData = readJsonObject(testCasesPath);

            // 解析测试数据
            QString dateStr = testData["rDate"].toString();
            qDebug() << "原始日期字符串:" << dateStr;

            // 提取日期部分（去掉时间部分）
            QString dateOnly = dateStr.split(" ")[0];
            QDate targetDate = QDate::fromString(dateOnly, "yyyy-MM-dd");
            qDebug() << "提取的日期部分:" << dateOnly << "解析结果:" << targetDate.toString("yyyy-MM-dd") << "有效性:" << targetDate.isValid();

            QString curTimeStr = testData["rCurTime"].toString();
            qDebug() << "当前时间字符串:" << curTimeStr;

            QTime curTime = parseTime(curTimeStr);

            // 解析日期到工作时间的映射
            QMap<QDate, QVector<CWorkTime>> dateToWorkTimeMap;
            QJsonObject rawDateToWorkTimeMap = testData["rDateToWorkTime"].toObject();

            qDebug() << "=== 解析工作时间映射 ===";
            qDebug() << "原始映射键数量:" << rawDateToWorkTimeMap.keys().size();

            for (auto it = rawDateToWorkTimeMap.begin(); it != rawDateToWorkTimeMap.end(); ++it) {
                QString dateKey = it.key();
                QJsonArray workTimeArray = it.value().toArray();
                QVector<CWorkTime> workTimeList;

                qDebug() << "原始日期键:" << dateKey << "工作时间段数量:" << workTimeArray.size();

                // 日期键已经是纯日期格式 "2025-02-27"，直接解析
                QDate dateKeyObj = QDate::fromString(dateKey, "yyyy-MM-dd");
                if (!dateKeyObj.isValid()) {
                    qWarning() << "❌ 无效的日期格式:" << dateKey;
                    continue;
                }

                for (const QJsonValue& workTimeValue : workTimeArray) {
                    QJsonObject workTimeObj = workTimeValue.toObject();

                    QString startTimeStr = workTimeObj["mWorkStartTime"].toString();
                    QString endTimeStr = workTimeObj["mWorkEndTime"].toString();

                    QTime startTime = parseTime(startTimeStr);
                    QTime endTime = parseTime(endTimeStr);

                    CWorkTime workTime;
                    workTime.update(startTime, endTime);
                    workTimeList.append(workTime);

                    qDebug() << "  工作时间段:" << startTime.toString("hh:mm:ss") << "-" << endTime.toString("hh:mm:ss");
                }

                dateToWorkTimeMap[dateKeyObj] = workTimeList;
                qDebug() << "✅ 添加日期映射:" << dateKeyObj.toString("yyyy-MM-dd") << "工作时间段数量:" << workTimeList.size();
            }

            qDebug() << "=== 最终测试数据汇总 ===";
            qDebug() << "目标日期:" << targetDate.toString("yyyy-MM-dd") << "有效性:" << targetDate.isValid();
            qDebug() << "当前时间:" << curTime.toString("hh:mm:ss") << "有效性:" << curTime.isValid();
            qDebug() << "工作时间映射中的日期:";
            for (auto it = dateToWorkTimeMap.begin(); it != dateToWorkTimeMap.end(); ++it) {
                qDebug() << "  -" << it.key().toString("yyyy-MM-dd") << "时间段数量:" << it.value().size();
            }

            // 检查目标日期是否在映射中
            if (!dateToWorkTimeMap.contains(targetDate)) {
                qWarning() << "❌ 目标日期" << targetDate.toString("yyyy-MM-dd") << "不在工作时间映射中!";
                qDebug() << "可用的日期:";
                for (auto it = dateToWorkTimeMap.begin(); it != dateToWorkTimeMap.end(); ++it) {
                    qDebug() << "  -" << it.key().toString("yyyy-MM-dd");
                }
                // 写入0作为结果
                writeResultToFile(resultFileName, 0);
                continue;
            }

            qDebug() << "✅ 目标日期在工作时间映射中找到";
            const QVector<CWorkTime>& workTimes = dateToWorkTimeMap[targetDate];
            qDebug() << "该日期的工作时间段数量:" << workTimes.size();
            for (int j = 0; j < workTimes.size(); ++j) {
                const CWorkTime& wt = workTimes[j];
                qDebug() << "  时间段" << j << ":" << wt.mWorkStartTime.toString("hh:mm:ss")
                         << "-" << wt.mWorkEndTime.toString("hh:mm:ss");
            }

            // 创建服务实例并执行测试
            CHolidaySet service;
            qDebug() << "=== 调用 TodayLeftSeconds 方法 ===";
            int result = service.TodayLeftSeconds(targetDate, curTime, dateToWorkTimeMap);

            // 调试：直接调用 OneDayLeftSeconds 来验证
            qDebug() << "=== 直接调用 OneDayLeftSeconds 验证 ===";
            if (!workTimes.isEmpty()) {
                int directResult = service.OneDayLeftSeconds(workTimes, curTime, workTimes.constLast().mWorkEndTime);
                qDebug() << "OneDayLeftSeconds 直接结果:" << directResult;
            }

            qDebug() << "=== 计算结果 ===";
            qDebug() << "TodayLeftSeconds 结果:" << result << "秒 (" << (result / 3600.0) << "小时)";

            // 写入测试结果
            writeResultToFile(resultFileName, result);

            qDebug() << "结果文件:" << resultFileName;
            qDebug() << "测试完成:" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50));

        } catch (const std::exception& e) {
            qWarning() << "测试失败:" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "错误:" << e.what();
        }
    }
}

void TodayLeftSecondsTest::cleanupTestCase()
{
    qDebug() << "清理 TodayLeftSeconds 测试用例...";
}
